/*!
 * \file wz_socket_core.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2015/12/25
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "config.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frservice_comm.h"
#include "frbyte_buffer.h"
#include "wz_socket_core.h"

extern void *g_p_apm_context;

typedef struct __st_L7session_wz_socket_private
{
    unsigned long ul_seq;                             //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                       //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frlist_header *p_lst_comm;
    Frlist_header *p_lst_req;
    Frbyte_Packet *p_req_packet;                      //存请求bytebuff数据
    Frbyte_Packet *p_resp_packet;                     //存相应bytebuff数据
}L7session_wz_socket_private;

/*!
 * wz_socket私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_wz_socket_private* __wz_socket_private_create(void)
{
    L7session_wz_socket_private *p_st_private = NULL;
    p_st_private = (L7session_wz_socket_private*)frmalloc(sizeof(L7session_wz_socket_private));
    if (p_st_private == NULL)
        return NULL;
    memset(p_st_private, 0x00, sizeof(L7session_wz_socket_private));

    return p_st_private;
}

/*!
 * 私有信息重置
 *
 * \param p_private_session  (wz_socket的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __wz_socket_session_reset(void *p_private_session)
{
    L7session_wz_socket_private *p_st_private = (L7session_wz_socket_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

    }
    return FR_SUCC;
}

/*!
 * 判断是否是wz_socket协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于wz_socket协议\n
 *         APM_L7_IS_NO   不属于wz_socket协议
 *
 * \note
 *
 */
int wz_socket_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
    unsigned int i_len = 0;
    char arr_len[8];

    if (p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len < 192 || p_st_conn==NULL)
        return APM_L7_IS_NO;

    memcpy(arr_len, p_st_packet->p_payload, 6);
    arr_len[6] = '\0';
    i_len = strtoul(arr_len, NULL, 10);
    if (i_len !=  p_st_packet->ui_payload_len - 6)
    	goto ERROR;

	//trsType
    if (memcmp(p_st_packet->p_payload+6, "\x30\x30\x30\x30", 4) != 0)
        goto ERROR;
	//Release
    if (memcmp(p_st_packet->p_payload+32, "\x31\x2e\x30\x30", 4) != 0)
        goto ERROR;
	//trans_type
    if (*(p_st_packet->p_payload+142) != '0' &&
    	*(p_st_packet->p_payload+142) != '1' &&
    	*(p_st_packet->p_payload+142) != '2' &&
    	*(p_st_packet->p_payload+142) != '3' &&
    	*(p_st_packet->p_payload+142) != 'B')
        goto ERROR;

    i_ret = frct_get_direct_known(p_st_conn);
    if (i_ret == FR_DIRECT_UNKNOWN)
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);

    return APM_L7_IS_YES;

ERROR:
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , L7session_wz_socket_private *p_st_private
                        , Frreport_body_data *p_st_body_data
                        , Conntrack *p_st_conn)
{
    int i_msg_len = 0;
    char *p_msg = NULL;
    char arr_name[32];
    char arr_header[2048];

	char arr_trsType[8], arr_Mac[32], arr_setTrscode[8], arr_Release[8], arr_setBranCode[16], arr_setTell[16], arr_setChkTell[16],
	arr_Chkpwd[32], arr_Chkcvv[32], arr_setAutTell[16], arr_Authpwd[32], arr_Authcvv[32], arr_setSeqno[32], arr_trans_type[2],
	arr_Linkflag[2], arr_Flushseqno[16], arr_Setdate[16], arr_Errdate[16], arr_Setdevid[16], arr_Appcode[16], arr_setMsglen[8];

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

	memset(arr_name, 0x00, sizeof(arr_name));
	memset(arr_header, 0x00, sizeof(arr_header));
	memset(arr_trsType, 0x00, sizeof(arr_trsType));
	memset(arr_Mac, 0x00, sizeof(arr_Mac));
	memset(arr_setTrscode, 0x00, sizeof(arr_setTrscode));
	memset(arr_Release, 0x00, sizeof(arr_Release));
	memset(arr_setBranCode, 0x00, sizeof(arr_setBranCode));
	memset(arr_setTell, 0x00, sizeof(arr_setTell));
	memset(arr_setChkTell, 0x00, sizeof(arr_setChkTell));
	memset(arr_Chkpwd, 0x00, sizeof(arr_Chkpwd));
	memset(arr_Chkcvv, 0x00, sizeof(arr_Chkcvv));
	memset(arr_setAutTell, 0x00, sizeof(arr_setAutTell));
	memset(arr_Authpwd, 0x00, sizeof(arr_Authpwd));
	memset(arr_Authcvv, 0x00, sizeof(arr_Authcvv));
	memset(arr_setSeqno, 0x00, sizeof(arr_setSeqno));
	memset(arr_trans_type, 0x00, sizeof(arr_trans_type));
	memset(arr_Linkflag, 0x00, sizeof(arr_Linkflag));
	memset(arr_Flushseqno, 0x00, sizeof(arr_Flushseqno));
	memset(arr_Setdate, 0x00, sizeof(arr_Setdate));
	memset(arr_Errdate, 0x00, sizeof(arr_Errdate));
	memset(arr_Setdevid, 0x00, sizeof(arr_Setdevid));
	memset(arr_Appcode, 0x00, sizeof(arr_Appcode));
	memset(arr_setMsglen, 0x00, sizeof(arr_setMsglen));

    if (bytebuff_remaining(p_packet) < 192)
        return APM_L7_ANALYZE_FAIL;

	//6位长度位
    if (bytebuff_skip(p_packet, 6) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //trsType
    if (bytebuff_get_bytes(p_packet, arr_trsType, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Mac
    if (bytebuff_get_bytes(p_packet, arr_Mac, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setTrscode
    if (bytebuff_get_bytes(p_packet, arr_setTrscode, 6) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Release
    if (bytebuff_get_bytes(p_packet, arr_Release, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setBranCode
    if (bytebuff_get_bytes(p_packet, arr_setBranCode, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_code", arr_setBranCode) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_name", arr_setBranCode) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setTell
    if (bytebuff_get_bytes(p_packet, arr_setTell, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setChkTell
    if (bytebuff_get_bytes(p_packet, arr_setChkTell, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Chkpwd
    if (bytebuff_get_bytes(p_packet, arr_Chkpwd, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Chkcvv
    if (bytebuff_get_bytes(p_packet, arr_Chkcvv, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setAutTell
    if (bytebuff_get_bytes(p_packet, arr_setAutTell, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Authpwd
    if (bytebuff_get_bytes(p_packet, arr_Authpwd, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Authcvv
    if (bytebuff_get_bytes(p_packet, arr_Authcvv, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setSeqno
    if (bytebuff_get_bytes(p_packet, arr_setSeqno, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //trans_type
    if (bytebuff_get_bytes(p_packet, arr_trans_type, 1) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	if (*arr_trans_type == '0')
		snprintf(arr_name, sizeof(arr_name), "正常交易");
	else if (*arr_trans_type == '1')
		snprintf(arr_name, sizeof(arr_name), "手工冲正交易");
	else if (*arr_trans_type == '2')
		snprintf(arr_name, sizeof(arr_name), "自动冲正");
	else if (*arr_trans_type == '3')
		snprintf(arr_name, sizeof(arr_name), "批量自动");
	else if (*arr_trans_type == 'B')
		snprintf(arr_name, sizeof(arr_name), "冲补账交易");

    if (frreport_body_l7_add_str(p_st_body_data, "transaction.title", arr_name) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_code", arr_name) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_name", arr_name) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Linkflag
    if (bytebuff_get_bytes(p_packet, arr_Linkflag, 1) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Flushseqno
    if (bytebuff_get_bytes(p_packet, arr_Flushseqno, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.code", arr_Flushseqno) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Setdate
    if (bytebuff_get_bytes(p_packet, arr_Setdate, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Errdate
    if (bytebuff_get_bytes(p_packet, arr_Errdate, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Setdevid
    if (bytebuff_get_bytes(p_packet, arr_Setdevid, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Appcode
    if (bytebuff_get_bytes(p_packet, arr_Appcode, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setMsglen
    if (bytebuff_get_bytes(p_packet, arr_setMsglen, 6) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    snprintf(arr_header, sizeof(arr_header),"trsType=%s,Mac=%s,setTrscode=%s,Release=%s,setBranCode=%s,setTell=%s,setChkTell=%s,Chkpwd=%s,Chkcvv=%s,setAutTell=%s,Authpwd=%s,Authcvv=%s,setSeqno=%s,trans_type=%s,Linkflag=%s,Flushseqno=%s,Setdate=%s,Errdate=%s,Setdevid=%s,Appcode=%s,setMsglen=%s",arr_trsType, arr_Mac, arr_setTrscode, arr_Release, arr_setBranCode, arr_setTell, arr_setChkTell, arr_Chkpwd,arr_Chkcvv, arr_setAutTell, arr_Authpwd, arr_Authcvv, arr_setSeqno, arr_trans_type, arr_Linkflag, arr_Flushseqno,arr_Setdate, arr_Errdate, arr_Setdevid, arr_Appcode, arr_setMsglen);
    if (frreport_body_l7_add_str(p_st_body_data, "request.wz_socket.header", arr_header) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    i_msg_len = strtoul(arr_setMsglen, NULL, 10);
    p_msg = (char *)frmalloc(i_msg_len+1);
    if (p_msg == NULL)
        goto ERROR;
    memset(p_msg, 0x00, i_msg_len+1);
    if (bytebuff_get_bytes(p_packet, p_msg, i_msg_len) == FR_FAIL)
        goto ERROR;
    if (frreport_body_l7_add_str(p_st_body_data, "request.wz_socket.msg", p_msg) == FR_FAIL)
        goto ERROR;
    frfree(p_msg);

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_msg)
        frfree(p_msg);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp数据解析
 *
 * \param p_packet   (resp数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , L7session_wz_socket_private *p_st_private
                         , Frreport_body_data *p_st_body_data
                         , Conntrack *p_st_conn)
{
	int i_msg_len = 0;
	char *p_msg = NULL;
	char arr_header[1024];

	char arr_trsType[8],arr_Mac[32],arr_setTell[16],arr_setSeqno[16],arr_gettrscode[8],arr_setDate[16],arr_Response[8],
	arr_Respdesc[128],arr_getdevid[16],arr_getbuflen[8];

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

	memset(arr_header, 0x00, sizeof(arr_header));
	memset(arr_trsType, 0x00, sizeof(arr_trsType));
	memset(arr_Mac, 0x00, sizeof(arr_Mac));
	memset(arr_setTell, 0x00, sizeof(arr_setTell));
	memset(arr_setSeqno, 0x00, sizeof(arr_setSeqno));
	memset(arr_gettrscode, 0x00, sizeof(arr_gettrscode));
	memset(arr_setDate, 0x00, sizeof(arr_setDate));
	memset(arr_Response, 0x00, sizeof(arr_Response));
	memset(arr_Respdesc, 0x00, sizeof(arr_Respdesc));
	memset(arr_getdevid, 0x00, sizeof(arr_getdevid));
	memset(arr_getbuflen, 0x00, sizeof(arr_getbuflen));

    if (bytebuff_remaining(p_packet) < 152)
        return APM_L7_ANALYZE_FAIL;

	//6位长度位
    if (bytebuff_skip(p_packet, 6) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //trsType
    if (bytebuff_get_bytes(p_packet, arr_trsType, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Mac
    if (bytebuff_get_bytes(p_packet, arr_Mac, 16) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setTell
    if (bytebuff_get_bytes(p_packet, arr_setTell, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setSeqno
    if (bytebuff_get_bytes(p_packet, arr_setSeqno, 8) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //gettrscode
    if (bytebuff_get_bytes(p_packet, arr_gettrscode, 6) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //setDate
    if (bytebuff_get_bytes(p_packet, arr_setDate, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Response
    if (bytebuff_get_bytes(p_packet, arr_Response, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_int(p_st_body_data, "response.code", atoi(arr_Response)) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "response.code_string", arr_Response) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //Respdesc
    if (bytebuff_get_bytes(p_packet, arr_Respdesc, 80) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //getdevid
    if (bytebuff_get_bytes(p_packet, arr_getdevid, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //getbuflen
    if (bytebuff_get_bytes(p_packet, arr_getbuflen, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    snprintf(arr_header, sizeof(arr_header),"trsType=%s,Mac=%s,setTell=%s,setSeqno=%s,gettrscode=%s,setDate=%s,Response=%s,Respdesc=%s,getdevid=%s,getbuflen=%s",arr_trsType, arr_Mac, arr_setTell, arr_setSeqno, arr_gettrscode, arr_setDate, arr_Response, arr_Respdesc, arr_getdevid, arr_getbuflen);
    if (frreport_body_l7_add_str(p_st_body_data, "response.wz_socket.header", arr_header) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    i_msg_len = strtoul(arr_getbuflen, NULL, 10);
    p_msg = (char *)frmalloc(i_msg_len+1);
    if (p_msg == NULL)
        goto ERROR;
    memset(p_msg, 0x00, i_msg_len+1);
    if (bytebuff_get_bytes(p_packet, p_msg, i_msg_len) == FR_FAIL)
        goto ERROR;
    if (frreport_body_l7_add_str(p_st_body_data, "response.wz_socket.msg", p_msg) == FR_FAIL)
        goto ERROR;
    frfree(p_msg);

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_msg)
        frfree(p_msg);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * wz_socket的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet       (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned int i_len = 0;
    char arr_len[8];
    L7session_wz_socket_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

	memset(arr_len, 0x00, sizeof(arr_len));

    p_st_private = (L7session_wz_socket_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //如果连续的两个request
    if (p_st_private->p_lst_comm)
        __wz_socket_session_reset((void *)(p_st_private));

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_req_packet == NULL)
        {
            p_st_private->p_req_packet = bytebuff_creat();
            if (p_st_private->p_req_packet == NULL)
                goto ERROR;
        }
    }
    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_req_packet == NULL)
        goto ERROR;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_req_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_bytes(p_st_private->p_req_packet, arr_len, 6) == FR_FAIL)
        goto ERROR;
    bytebuff_rewind(p_st_private->p_req_packet);
    i_len = strtoul(arr_len, NULL, 10);
    if (p_st_private->p_req_packet->ui_all_len <  i_len - 6)
    	return APM_L7_ANALYZE_TODO;

    //req解析
    i_ret = __req_parse(p_st_private->p_req_packet, p_st_private, p_st_private->p_st_body_data_req, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    //拷贝相关链表
    p_st_private->p_lst_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_comm == NULL)
        goto ERROR;
    p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_req == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;
    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;

    if (p_st_private->p_req_packet)
    {
        bytebuff_free(&p_st_private->p_req_packet);
        p_st_private->p_req_packet = NULL;
    }

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __wz_socket_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * wz_socket的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet       (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned int i_len = 0;
    unsigned long ul_tmp = 0;
    char arr_len[8];
    L7session_wz_socket_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

	memset(arr_len, 0x00, sizeof(arr_len));

    p_st_private = (L7session_wz_socket_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_private->p_st_body_data_resp == NULL)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_resp_packet == NULL)
        {
            p_st_private->p_resp_packet = bytebuff_creat();
            if (p_st_private->p_resp_packet == NULL)
                goto ERROR;
        }
    }

    /* 请求的字节数 */
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_resp_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_bytes(p_st_private->p_resp_packet, arr_len, 6) == FR_FAIL)
        goto ERROR;
    bytebuff_rewind(p_st_private->p_resp_packet);
    i_len = strtoul(arr_len, NULL, 10);
    if (p_st_private->p_resp_packet->ui_all_len <  i_len - 6)
    	return APM_L7_ANALYZE_TODO;

    //resp解析
    i_ret = __resp_parse(p_st_private->p_resp_packet, p_st_private, p_st_private->p_st_body_data_resp, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    if (p_st_l4_trans->st_request_time_first_byte.tv_sec != 0)
    {
        FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req);
        FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm);
    }
    else
    {
        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn) == FR_FAIL)
            goto ERROR;
    }

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    if (p_st_l4_trans->st_request_time.tv_sec != 0 || p_st_l4_trans->st_request_time.tv_usec != 0)
    {
        //server time
        ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time), &(p_st_l4_trans->st_response_time_first_byte));
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
            goto ERROR;
    }
    else
    {
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
            goto ERROR;
    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    __wz_socket_session_reset((void *)(p_st_private));
    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __wz_socket_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * wz_socket的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
int wz_socket_analysis(Conntrack *p_st_conn
                           , Apm_packet *p_st_packet
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin、syn包的话销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        wz_socket_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __wz_socket_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    //response
    else
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    if (p_st_session->p_session_private)
        wz_socket_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (wz_socket的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int wz_socket_session_destroy(void *p_private_session)
{
    L7session_wz_socket_private *p_st_private = (L7session_wz_socket_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }
    return FR_SUCC;
}
